import asyncio

from aiogram import Router, types, F
from aiogram.filters import StateFilter
from aiogram.fsm.context import FSMContext
from loguru import logger as log

from database import models
from tg_bot.filters.user_filter import IsAdmin
from tg_bot.keyboards import inline, callback_factory
from tg_bot.services.text import not_correct_input
from tg_bot.states.admin import AdminCmd, AdminSeat, AdminSeatSetting

SEAT_TEXT = 'Меню посадок: '


dp = Router()
dp.message.filter(IsAdmin(is_admin=True))
dp.callback_query.filter(IsAdmin())


async def admin_seat_menu_message(message: types.Message,
                                  state: FSMContext):
    data = await state.get_data()
    current_page = data.get('SeatPaginator_page', 1)
    key = inline.SeatPaginator(
        dp,
        current_page=current_page,
        before_pagination_keyboards=[
            await inline.find_keyboard('Посадки', 'seat'),
            await inline.add_seat()],
        after_pagination_keyboards=[await inline.back('admin_menu')]
    )
    try:
        await message.edit_text(SEAT_TEXT, reply_markup=key.as_markup())
    except Exception as e:
        log.warning(e)
        await message.answer(SEAT_TEXT, reply_markup=key.as_markup())
    await state.set_state(AdminSeat.main)


@dp.callback_query(callback_factory.AdminMenuCall.filter(
    F.item == 'seat'
), AdminCmd.main)
@dp.callback_query(callback_factory.BackCall.filter(
    F.to == 'seat_menu'
), AdminSeatSetting.main)
@dp.callback_query(callback_factory.ActionCall.filter(F.action == 'cancel'),
                   AdminSeat.add)
async def admin_seat_menu(call: types.CallbackQuery, state: FSMContext):
    await admin_seat_menu_message(call.message, state)


@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action == 'add_seat'
), AdminSeat.main)
async def admin_add_seat_call(call: types.CallbackQuery, state: FSMContext):
    text = 'Введите название для стола: '
    key = await inline.cancel()
    try:
        await call.message.edit_text(text, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(text, reply_markup=key)
    await state.set_state(AdminSeat.add)


@dp.message(AdminSeat.add)
async def admin_add_seat(message: types.Message, state: FSMContext):
    if models.Seat.objects.filter(name=message.text).first():
        await not_correct_input(message, 'Стол с таким названием уже существует!')
    else:
        models.Seat.objects.create(name=message.text)
        await admin_seat_menu_message(message, state)


@dp.message(F.text.startswith('SEAT'), F.via_bot, AdminSeat.main)
async def seat_settings_inline(message: types.Message, state: FSMContext):
    seat_pk: int = int(message.text.replace('SEAT ', ''))
    seat: models.Seat = models.Seat.objects.filter(pk=seat_pk).first()
    text = seat.get_name()
    key = await inline.seat_settings(back_to='seat_menu')
    await message.answer(text, reply_markup=key)
    await state.set_state(AdminSeatSetting.main)
    await state.update_data({'seat': seat})


@dp.callback_query(callback_factory.SeatCall.filter(), AdminSeat.main)
async def seat_settings(call: types.CallbackQuery,
                        state: FSMContext,
                        callback_data: callback_factory.SeatCall):
    seat = models.Seat.objects.filter(pk=callback_data.pk).first()
    text = seat.get_name()
    key = await inline.seat_settings(back_to='seat_menu')
    try:
        await call.message.edit_text(text, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(text, reply_markup=key)
    await state.set_state(AdminSeatSetting.main)
    await state.update_data({'seat': seat})


@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action == 'change_seat_name'
), AdminSeatSetting.main)
@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action == 'change_seat_max'
), AdminSeatSetting.main)
@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action == 'change_seat_photo'
), AdminSeatSetting.main)
async def change_seat_name_call(call: types.CallbackQuery, state: FSMContext,
                                callback_data: callback_factory.AdminActionCall):
    match callback_data.action:
        case 'change_seat_name':
            text = 'Введите новое название: '
            await state.set_state(AdminSeatSetting.name)
        case 'change_seat_max':
            text = 'Введите максимальную вместимость: '
            await state.set_state(AdminSeatSetting.max_count)
        case _:
            text = 'Отправьте новое фото: '
            await state.set_state(AdminSeatSetting.photo)
    key = await inline.cancel()
    try:
        await call.message.edit_text(text, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(text, reply_markup=key)


@dp.callback_query(callback_factory.AdminActionCall.filter(
    F.action == 'delete_seat'
), AdminSeatSetting.main)
async def delete_seat_confirmation(call: types.CallbackQuery, state: FSMContext):
    text = 'Вы уверены, что хотите удалить?'
    key = await inline.confirm_or_cancel()
    try:
        await call.message.edit_text(text, reply_markup=key)
    except Exception as e:
        log.warning(e)
        await call.message.answer(text, reply_markup=key)
    await state.set_state(AdminSeatSetting.delete)


@dp.callback_query(callback_factory.ActionCall.filter(F.action == 'cancel'),
                   StateFilter(AdminSeatSetting.name,
                               AdminSeatSetting.max_count,
                               AdminSeatSetting.photo,
                               AdminSeatSetting.delete))
async def change_seat_cancel(call: types.CallbackQuery, state: FSMContext):
    data = await state.get_data()
    seat: models.Seat = data.get('seat')
    callback_data = callback_factory.SeatCall(pk=seat.pk)
    await seat_settings(call, state, callback_data)


@dp.callback_query(callback_factory.ActionCall.filter(F.action == 'confirm'), AdminSeatSetting.delete)
async def confirm_seat_delete(call: types.CallbackQuery, state: FSMContext):
    data = await state.get_data()
    seat: models.Seat = data.get('seat')
    seat.delete()
    await admin_seat_menu(call, state)


@dp.message(AdminSeatSetting.name)
async def change_seat_name(message: types.Message, state: FSMContext):
    data = await state.get_data()
    seat: models.Seat = data.get('seat')
    if models.Seat.objects.filter(name=message.text).first():
        await not_correct_input(message, 'Стол с таким названием уже существует!')
    else:
        seat.name = message.text
        seat.save()
        await message.answer(f'{seat.get_name()}', reply_markup=await inline.seat_settings(back_to='seat_menu'))
        await state.set_state(AdminSeatSetting.main)


@dp.message(AdminSeatSetting.max_count)
async def change_seat_max(message: types.Message, state: FSMContext):
    data = await state.get_data()
    seat: models.Seat = data.get('seat')
    if message.text.isdigit():
        seat.max_count = int(message.text)
        seat.save()
        await message.answer(f'{seat.get_name()}', reply_markup=await inline.seat_settings(back_to='seat_menu'))
        await state.set_state(AdminSeatSetting.main)
    else:
        await message.delete()
        msg = await message.answer('Неверный ввод! Введите число')
        await asyncio.sleep(2)
        await msg.delete()


@dp.message(AdminSeatSetting.photo)
async def change_seat_photo(message: types.Message, state: FSMContext):
    data = await state.get_data()
    seat: models.Seat = data.get('seat')
    if message.photo:
        seat.photo = message.photo[-1].file_id
        seat.save()
        await message.answer(f'{seat.get_name()}', reply_markup=await inline.seat_settings(back_to='seat_menu'))
        await state.set_state(AdminSeatSetting.main)
    else:
        await not_correct_input(message, 'Отправьте фото!')
